package cn.autumnorange.app.common.repository.impl;

import cn.autumnorange.app.common.repository.AbstractRepository;
import cn.autumnorange.app.common.service.Persistable;
import org.hibernate.transform.Transformers;
import org.hibernate.type.Type;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public abstract class AbstractRepositoryImpl<X extends Persistable, I extends Serializable>
        extends AbstractPersisTableRepositoryImpl<I> implements AbstractRepository<X, I> {
    // 反射对象 获取实体X的Class
    private final Class<X> clazz;

    /**
     * 构造函数反射泛型对象真实类型
     */
    public AbstractRepositoryImpl() {
        //    获取new对象的泛型父类
        ParameterizedType pType = (ParameterizedType) this.getClass().getGenericSuperclass();
        // 获取类型参数的真是值，就是泛型参数的个数；
        this.clazz = (Class<X>) pType.getActualTypeArguments()[0];
        //    java.lang.String className = clazz.getSimpleName();
    }

    @Override
    public Class<X> getClazz() {
        return clazz;
    }

    @Override
    public X save(X entity) {
        super.save(entity);
        return entity;
    }

    @Override
    public X update(X entity) {
        return super.update(entity);
    }

    @Override
    public X saveOrUpdate(X entity) {
        if (entity.getId() != null) {
            super.save(entity);
        } else {
            super.update(entity);
        }
        return entity;
    }

    @Override
    public X findById(I id) {
        return super.findById(this.clazz, id);
    }

    @Override
    public List<X> findByFiled(String filed, Object o) {
        return super.findByFiled(this.clazz, filed, o);
    }

    @Override
    public List<X> findByFileds(LinkedHashMap<String, Object> linkedHashMap) {
        return super.findByFileds(this.clazz, linkedHashMap);
    }

    @Override
    public List<X> findAll() {
        return super.findAll(this.clazz);
    }

    @Override
    public List<X> findByNativeQuery(String sql, Map<String, Object> conditionParams, Map<String, Type> scalar) {
        return super.findByNativeQuery(sql, conditionParams, Transformers.aliasToBean(getClazz()), scalar);
    }

    @Override
    public List<X> findPageByQueryFiled(String filed, Object o, int pageNo, int pageSize) {
        return super.findPageByQueryFiled(this.clazz, filed, o, pageNo, pageSize);
    }

    @Override
    public Map<String, Object> findPageByNativeQueryFileds(
            String sql, Map<String, Object> conditionParams, Integer pageNo, Integer pageSize) {
        return super.findPageByNativeQueryFileds(
                sql, conditionParams, Transformers.aliasToBean(getClazz()), pageNo, pageSize);
    }

    @Override
    public Integer updateFileds(
            String hql, Map<String, Object> conditionParams, Map<String, Object> valueParams) {
        return super.updateFileds(this.clazz, hql, conditionParams, valueParams);
    }

    @Override
    public boolean remove(X entity) {
        return super.remove(entity);
    }

    @Override
    public boolean deleteById(I id) {
        return super.deleteById(this.clazz, id);
    }

    @Override
    public boolean deleteByMap(Map paramsMap) {
        return super.deleteByMap(this.clazz, paramsMap);
    }

    @Override
    public boolean deleteByMap(Map paramsMap, String hql) {
        return super.deleteByMap(this.clazz, hql, paramsMap);
    }

    @Override
    public X findByIdClass(X entity, Object id) {
        return super.findByIdClass(entity, id);
    }

    // ---------------------------------first

    @Override
    public X first(String hql) {
        return super.first(this.clazz, hql);
    }

    @Override
    public X first(String hql, Object arg) {
        return super.first(this.clazz, hql, arg);
    }

    @Override
    public X first(String hql, Object arg, Object arg2) {
        return super.first(this.clazz, hql, arg, arg2);
    }

    @Override
    public X first(String hql, Object... args) {
        return super.first(this.clazz, hql, args);
    }

    // ---------------------------------single
    @Override
    public X single(String hql) {
        return super.single(this.clazz, hql);
    }

    @Override
    public X single(String hql, Object arg) {
        return super.single(this.clazz, hql, arg);
    }

    @Override
    public X single(String hql, Object arg, Object arg2) {
        return super.single(this.clazz, hql, arg, arg2);
    }

    @Override
    public X single(String hql, Object... args) {
        return super.single(this.clazz, hql, args);
    }

    // ---------------------------------list
    @Override
    public List<X> list(String hql) {
        return super.list(this.clazz, hql);
    }

    @Override
    public List<X> list(String hql, Object arg) {
        return super.list(this.clazz, hql, arg);
    }

    @Override
    public List<X> list(String hql, Object arg, Object arg2) {
        return super.list(this.clazz, hql, arg, arg2);
    }

    @Override
    public List<X> list(String hql, Object... args) {
        return super.list(this.clazz, hql, args);
    }

    // ---------------------------------top
    @Override
    public List<X> top(int top, String hql) {
        return super.top(top, this.clazz, hql);
    }

    @Override
    public List<X> top(int top, String hql, Object arg) {
        return super.top(top, this.clazz, hql, arg);
    }

    @Override
    public List<X> top(int top, String hql, Object arg, Object arg2) {
        return super.top(top, this.clazz, hql, arg, arg2);
    }

    @Override
    public List<X> top(int top, String hql, Object... args) {
        return super.top(top, this.clazz, hql, args);
    }
}
